package com.podcstr.controller;

import com.podcstr.entity.Category;
import com.podcstr.entity.MediaFile;
import com.podcstr.entity.Podcast;
import com.podcstr.qualifier.CurrentSession;
import com.podcstr.service.MediaFileService;
import com.podcstr.service.PodcastService;
import com.podcstr.service.exception.ServiceException;
import com.podcstr.session.UserSession;
import org.apache.log4j.Logger;
import org.primefaces.model.UploadedFile;

import javax.annotation.PostConstruct;
import javax.ejb.EJB;
import javax.enterprise.context.SessionScoped;
import javax.faces.application.FacesMessage;
import javax.faces.context.FacesContext;
import javax.inject.Inject;
import javax.inject.Named;
import java.io.*;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

/**
 * @author azim
 * @since 5/19/13 
 */

@Named
@SessionScoped
public class PodcastController implements Serializable {

    private final Logger log = Logger.getLogger(PodcastController.class.getName());

    private Podcast podcast;

    private Category category;

    private UploadedFile albumArt;

    private UploadedFile podcastFile;

    private List<Podcast> podcasts;

    private List<Podcast> searchedPodcasts;

    private String word = "search";

    @Inject
    @CurrentSession
    private UserSession userSession;

    @EJB
    private PodcastService podcastService;

    @EJB
    private MediaFileService mediaFileService;

    @PostConstruct
    public void init() {

        if (podcast == null) {
            podcast = new Podcast();
            category = new Category();
        }

        podcasts = podcastService.findAll();
    }

    //Getters and setters for podcast controller

    public Podcast getPodcast() {
        return podcast;
    }

    public void setPodcast(Podcast podcast) {
        this.podcast = podcast;
    }

    public Category getCategory() {
        return category;
    }

    public void setCategory(Category category) {
        this.category = category;
    }

    public PodcastService getPodcastService() {
        return podcastService;
    }

    public UploadedFile getAlbumArt() {

        return albumArt;
    }

    public void setAlbumArt(UploadedFile albumArt) {
        this.albumArt = albumArt;
    }

    public UploadedFile getPodcastFile() {
        return podcastFile;
    }

    public void setPodcastFile(UploadedFile podcastFile) {
        this.podcastFile = podcastFile;
    }

    public void setPodcastService(PodcastService podcastService) {
        this.podcastService = podcastService;
    }

    public List<Podcast> getPodcasts() {

        return podcasts;
    }

    public String getWord() {
        return word;
    }

    public void setWord(String word) {
        this.word = word;
    }

    public List<Podcast> getSearchedPodcasts() {
        return searchedPodcasts;
    }

    public void setSearchedPodcasts(List<Podcast> searchedPodcasts) {
        this.searchedPodcasts = searchedPodcasts;
    }

    //Other required methods for podcast controller

    public void sort(String sortBy) {

        log.info("in the sort." + sortBy);

        if (sortBy.equals("recent")) {

            Collections.sort(podcasts, Podcast.CompareByDateCreated);
            Collections.reverse(podcasts);
        } else if (sortBy.equals("alphabetical")) {

            Collections.sort(podcasts, Podcast.CompareByName);
        } else {

            Collections.sort(podcasts, new Comparator<Podcast>() {
                @Override
                public int compare(Podcast o1, Podcast o2) {

                    return ((Long) (o1.getRating())).compareTo(((Long) (o2.getRating())));
                }
            });
            Collections.reverse(podcasts);
        }

    }

    public List<Podcast> showUserPodcast() {

        return podcastService.findByUserId(userSession.getUser().getId());
    }

    public long countPodcastByUserId(long userId) {

        return podcastService.countPodcastByUserId(userId);
    }

    public String searchPodcast() {

        if(word != null)
        {
            searchedPodcasts =  podcastService.searchPodcast(word);
        }

        else
        {
            searchedPodcasts = new ArrayList<Podcast>();
        }

        return "search_podcast.xhtml?faces-redirect=true";
    }

    public String showAddForm() {

        podcast = new Podcast();
        return "login_add_podcast.xhtml?faces-redirect=true";
    }

    public void add() throws IOException {

        FacesContext context = FacesContext.getCurrentInstance();

        if (podcast != null && albumArt != null && podcastFile != null) {
            try {

                //Finding the correct user

                podcast.setUser(userSession.getUser());
                podcast.setCategory(category);

                //Setting the album art

                MediaFile mediaFile = new MediaFile();

                if (albumArt != null) {
                    mediaFile.setName(albumArt.getFileName());
                    mediaFile.setContentType(albumArt.getContentType());
                    mediaFile.setContent(albumArt.getContents());
                    podcast.setAlbumArt(mediaFile);
                }

                //Setting the audio mediaFile

                mediaFile = new MediaFile();
                mediaFile.setName(podcastFile.getFileName());
                mediaFile.setContentType(podcastFile.getContentType());
                mediaFile.setContent(podcastFile.getContents());
                podcast.setAudio(mediaFile);

                podcastService.add(podcast);
                podcasts.add(podcast);
                context.addMessage(null, new FacesMessage("Successfully Added the '" + podcast.getName() + "' Podcast."));
            } catch (ServiceException e) {

                if (e.getViolations().size() != 0) {
                    context.addMessage(null, new FacesMessage(e.getViolations().toString()));
                }
                context.addMessage(null, new FacesMessage(e.getMessage()));
            }
        }

        showAddForm();
    }

    public boolean createAudioFile(MediaFile audio) {

        InputStream inputStream = null;
        OutputStream outputStream = null;

        FacesContext context = FacesContext.getCurrentInstance();

        //Constructing path

        String path = FacesContext.getCurrentInstance().getExternalContext().getRealPath("/");
        path += "resources" + File.separator;
        path += "media";
        log.info("path : " + path);

        try {

            //creating the directory if it does not exists.

            File directory = new File(path);
            if (!directory.exists()) {
                directory.mkdirs();
            }

            //creating the audio file if it does not exists.

            path += File.separator + audio.getName();
            File audioFile = new File(path);
            if (!audioFile.exists()) {
                audioFile.createNewFile();

                //Setting file permission

                audioFile.setExecutable(true);
                audioFile.setReadable(true);
                audioFile.setWritable(true);
                String os = System.getProperty("os.name").toLowerCase();
                if (os.indexOf("nix") >= 0 || os.indexOf("nux") >= 0) {
                    Runtime.getRuntime().exec("chmod 777 " + path);
                }

                // writing contents to the audio file

                inputStream = new ByteArrayInputStream(audio.getContent());
                outputStream = new FileOutputStream(audioFile);

                int read = 0;
                while ((read = inputStream.read()) != -1) {
                    outputStream.write(read);
                }
                inputStream.close();
                outputStream.close();
            }
            return true;

        } catch (IOException ioe) {

            ioe.printStackTrace();
            return false;
        }
    }

    public String listenPodcast() {

        FacesContext context = FacesContext.getCurrentInstance();
        String podcastName = context.getExternalContext().getRequestParameterMap().get("podcastName");
        podcast = podcastService.findByPodcastName(podcastName);

        if (podcast != null) {

            if (createAudioFile(podcast.getAudio()) == true) {
                return "listen_podcast.xhtml?faces-redirect=true";
            } else {
                context.addMessage(null, new FacesMessage("Error Streaming the audio file."));
            }
        }

        return null;
    }

}
